package core

import (
	"github.com/asynkron/protoactor-go/actor"
	"github.com/louloulin/dataflare/pkg/messages"
)

// ActorRef 是对Actor的引用
type ActorRef interface {
	// Tell 向Actor发送消息
	Tell(message interface{})
	// Request 向Actor发送请求并等待响应
	Request(message interface{}, timeout int) (interface{}, error)
}

// ActorRefImpl 是ActorRef的实现
type ActorRefImpl struct {
	pid    *actor.PID
	system *actor.ActorSystem
}

// NewActorRef 创建一个新的ActorRef
func NewActorRef(pid *actor.PID, system *actor.ActorSystem) ActorRef {
	return &ActorRefImpl{
		pid:    pid,
		system: system,
	}
}

// Tell 向Actor发送消息
func (a *ActorRefImpl) Tell(message interface{}) {
	a.system.Root.Send(a.pid, message)
}

// Request 向Actor发送请求并等待响应
func (a *ActorRefImpl) Request(message interface{}, timeout int) (interface{}, error) {
	future := a.system.Root.RequestFuture(a.pid, message, timeout)
	return future.Result()
}

// ActorFactory 是创建Actor的工厂
type ActorFactory interface {
	// CreateActor 创建一个新的Actor
	CreateActor(props *actor.Props) (ActorRef, error)
	// CreateNamedActor 创建一个命名的Actor
	CreateNamedActor(props *actor.Props, name string) (ActorRef, error)
}

// ActorFactoryImpl 是ActorFactory的实现
type ActorFactoryImpl struct {
	system *actor.ActorSystem
}

// NewActorFactory 创建一个新的ActorFactory
func NewActorFactory(system *actor.ActorSystem) ActorFactory {
	return &ActorFactoryImpl{
		system: system,
	}
}

// CreateActor 创建一个新的Actor
func (f *ActorFactoryImpl) CreateActor(props *actor.Props) (ActorRef, error) {
	pid, err := f.system.Root.SpawnNamed(props, "")
	if err != nil {
		return nil, err
	}
	return NewActorRef(pid, f.system), nil
}

// CreateNamedActor 创建一个命名的Actor
func (f *ActorFactoryImpl) CreateNamedActor(props *actor.Props, name string) (ActorRef, error) {
	pid, err := f.system.Root.SpawnNamed(props, name)
	if err != nil {
		return nil, err
	}
	return NewActorRef(pid, f.system), nil
}

// SupervisorStrategy 是Actor监督策略
type SupervisorStrategy interface {
	// HandleFailure 处理Actor失败
	HandleFailure(supervisor ActorRef, child ActorRef, reason error)
}

// OneForOneStrategy 是一对一监督策略
type OneForOneStrategy struct {
	maxRetries int
	decider    func(reason error) actor.Directive
}

// NewOneForOneStrategy 创建一个新的一对一监督策略
func NewOneForOneStrategy(maxRetries int, decider func(reason error) actor.Directive) SupervisorStrategy {
	return &OneForOneStrategy{
		maxRetries: maxRetries,
		decider:    decider,
	}
}

// HandleFailure 处理Actor失败
func (s *OneForOneStrategy) HandleFailure(supervisor ActorRef, child ActorRef, reason error) {
	// 根据错误类型决定如何处理
	switch reason.(type) {
	case *messages.CriticalError:
		// 停止Actor
		child.Tell(&actor.Stop{})
	case *messages.TemporaryError:
		// 重启Actor
		child.Tell(&actor.Restart{})
	default:
		// 使用决策器
		directive := s.decider(reason)
		switch directive {
		case actor.RestartDirective:
			child.Tell(&actor.Restart{})
		case actor.StopDirective:
			child.Tell(&actor.Stop{})
		case actor.ResumeDirective:
			// 继续执行
		case actor.EscalateDirective:
			// 上报给上级监督者
			supervisor.Tell(&messages.ErrorMessage{
				Error:    reason,
				Severity: "escalated",
			})
		}
	}
}
